﻿using Als.Common.String;
using System;
using System.Configuration;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace Als.Common.Net
{
    public static class UrlHelper
    {
        private static readonly System.Text.Encoding Encoding = System.Text.Encoding.UTF8;

        #region URL64位编码

        /// <summary>
        /// URL64位编码
        /// </summary>
        /// <param name="sourthUrl"></param>
        /// <returns></returns>
        public static string Base64Encrypt(this string sourthUrl)
        {
            var eurl = HttpUtility.UrlEncode(sourthUrl);
            eurl = Convert.ToBase64String(Encoding.GetBytes(eurl ?? throw new InvalidOperationException("URL不能为空")));
            return eurl;
        }

        /// <summary>
        /// URL64位解码
        /// </summary>
        /// <param name="eStr"></param>
        /// <returns></returns>
        public static string Base64Decrypt(this string eStr)
        {
            if (!eStr.IsBase64())
            {
                return eStr;
            }
            var buffer = Convert.FromBase64String(eStr);
            var sourthUrl = Encoding.GetString(buffer);
            sourthUrl = HttpUtility.UrlDecode(sourthUrl);
            return sourthUrl;
        }

        
        #endregion

        #region URL编码

        /// <summary>
        /// URL字符串编码
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>编码结果</returns>
        public static string UrlEncode(this string str)
        {
            return HttpUtility.UrlEncode(str);
        }

        /// <summary>
        /// URL字符串解码
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>解码结果</returns>
        public static string UrlDecode(this string str)
        {
            return HttpUtility.UrlDecode(str);
        }

        #endregion

        #region URL参数操作

        /// <summary>
        /// 添加URL参数
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="paramName">参数名</param>
        /// <param name="value">参数值</param>
        /// <returns></returns>
        public static string AddParam(string url, string paramName, string value)
        {
            var uri = new Uri(url);
            if (string.IsNullOrEmpty(uri.Query))
            {
                var eval = HttpContext.Current.Server.UrlEncode(value);
                return string.Concat(url, "?" + paramName + "=" + eval);
            }
            else
            {
                var eval = HttpContext.Current.Server.UrlEncode(value);
                return string.Concat(url, "&" + paramName + "=" + eval);
            }
        }

        /// <summary>
        /// 更新URL参数
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="paramName">参数名</param>
        /// <param name="value">参数值</param>
        /// <returns></returns>
        public static string UpdateParam(string url, string paramName, string value)
        {
            var keyWord = paramName + "=";
            var index = url.IndexOf(keyWord, StringComparison.Ordinal) + keyWord.Length;
            var index1 = url.IndexOf("&", index, StringComparison.Ordinal);
            if (index1 == -1)
            {
                url = url.Remove(index, url.Length - index);
                url = string.Concat(url, value);
                return url;
            }
            url = url.Remove(index, index1 - index);
            url = url.Insert(index, value);
            return url;
        }

        #endregion

        #region 自动识别文本中URL
        /// <summary> 
        /// 自动识别文本中的URL
        /// 可以识别 www.，http://， ftp://， xx@xx.xx， mms:// 
        /// </summary> 
        /// <param name="input">输入数据</param> 
        /// <returns>自动识别URL后的数据</returns> 
        public static string AutoConvertToUrl(object input)
        {
            var str = input.ToString();
            var reg = new Regex("([^\\]=>])(http://[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)");
            str = reg.Replace(str, "$1<a href=\"$2\" target=\"_blank\">$2</a>");
            reg = new Regex("^(http://[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)");
            str = reg.Replace(str, "<a href=\"$1\" target=\"_blank\">$1</a>");
            reg = new Regex("(http://[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)$");
            str = reg.Replace(str, "<a href=\"$1\" target=\"_blank\">$1</a>");
            reg = new Regex("([^\\]=>])(ftp://[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)");
            str = reg.Replace(str, "$1<a href=\"$2\" target=\"_blank\">$2</a>");
            reg = new Regex("^(ftp://[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)");
            str = reg.Replace(str, "<a href=\"$1\" target=\"_blank\">$1</a>");
            reg = new Regex("(ftp://[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)$");
            str = reg.Replace(str, "<a href=\"$1\" target=\"_blank\">$1</a>");
            reg = new Regex("([^\\]=>])(mms://[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)");
            str = reg.Replace(str, "$1<a href=\"$2\" target=\"_blank\">$2</a>");
            reg = new Regex("^(mms://[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)");
            str = reg.Replace(str, "<a href=\"$1\" target=\"_blank\">$1</a>");
            reg = new Regex("(mms://[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)$");
            str = reg.Replace(str, "<a href=\"$1\" target=\"_blank\">$1</a>");
            reg = new Regex("([a-z0-9_A-Z\\-\\.]{1,20})@([a-z0-9_\\-]{1,15})\\.([a-z]{2,4})");
            str = reg.Replace(str, "<a href=\"mailto:$1@$2.$3\" target=\"_blank\">$1@$2.$3</a>");
            reg = new Regex("([^/])(www.[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)");
            str = reg.Replace(str, "$1<a href=\"http://$2\" target=\"_blank\">$2</a>");
            reg = new Regex("^(www.[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)");
            str = reg.Replace(str, "<a href=\"http://$1\" target=\"_blank\">$1</a>");
            reg = new Regex("(www.[A-Za-z0-9\\./=\\?%\\-&_~`@':+!]+)$");
            str = reg.Replace(str, "<a href=\"http://$1\" target=\"_blank\">$1</a>");
            return str;
        }

        #endregion

        #region 鉴权URL

        /// <summary>
        /// 验证鉴权地址
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="authKey">秘钥</param>
        /// <returns></returns>
        public static bool CheckUrl(string url, string authKey)
        {
            var privateKey = "AuthUrlKey".ValueOfAppSetting();
            var array = authKey.Split('-');
            var timestamp = array[0];
            var md5Value = array[3];
            var s = $"{url}-{timestamp}-{0}-{0}-{privateKey}";
            //如果手机时间与当前服务器时间相差5分钟，鉴权失败
            if (!ValidateDateTime(timestamp))
            {
                return false;
            }
            s = Md5Sum(s);
            return s == md5Value;
        }

        /// <summary>
        /// 验证客户端与服务端的有效时间
        /// </summary>
        /// <param name="timestamp">时间戳</param>
        /// <returns></returns>
        public static bool ValidateDateTime(string timestamp)
        {
            var jsTimeStamp = Convert.ToInt64(timestamp);
            var startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            var clientTime = startTime.AddMilliseconds(jsTimeStamp);
            return !(Math.Abs((DateTime.Now - clientTime).TotalMinutes) > 10);
        }

        /// <summary>
        /// 创建授权url
        /// </summary>
        /// <param name="url"></param>
        /// <param name="domain"></param>
        /// <returns></returns>
        public static string CreatAuthUrl(string url, string domain)
        {
            var privateKey = "AuthUrlKey".ValueOfAppSetting();
            var timeStamp = ConvertDateTime(DateTime.Now);
            var s = $"{url}-{timeStamp}-{0}-{0}-{privateKey}";
            var authKey = Md5Sum(s);
            var result = $"{timeStamp}-{0}-{0}-{authKey}";
            if (url.Contains("?"))
            {
                return url + "&auth_key=" + result;
            }
            else
            {
                return url + "?auth_key=" + result;
            }
        }

        #endregion




        #region 内部方法

        /// <summary>
        /// 字符串MD5
        /// </summary>
        /// <param name="strToEncrypt"></param>
        /// <returns></returns>
        private static string Md5Sum(string strToEncrypt)
        {
            var bs = Encoding.UTF8.GetBytes(strToEncrypt);
            return Md5Sum(bs);
        }

        /// <summary>
        /// 二进制MD5
        /// </summary>
        /// <param name="bs"></param>
        /// <returns></returns>
        private static string Md5Sum(byte[] bs)
        {
            // 创建md5 对象  
            var md5 = MD5.Create();
            // 生成16位的二进制校验码  
            var hashBytes = md5.ComputeHash(bs);
            // 转为32位字符串  
            var hashString = "";
            foreach (var t in hashBytes)
            {
                hashString += Convert.ToString(t, 16).PadLeft(2, '0');
            }
            return hashString.PadLeft(32, '0');
        }

        /// <summary>
        /// 时间戳
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        private static string ConvertDateTime(DateTime dt)
        {
            var startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区
            var timeStamp = (long)(dt - startTime).TotalMilliseconds; // 相差毫秒数
            return timeStamp.ToString();
        }

        #endregion
    }
}
